/*
    IceCode toolkit - Test Framework.
    Copyright (C) 2011 Alfredo 'IceCoder' Mungo

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _ICECODE_GALILEI_TIMEDTEST
#define _ICECODE_GALILEI_TIMEDTEST

#include <ctime>
#include <errno.h>
#include <iomanip>
#include "Test.hpp"
#include "print_macros.hpp"

namespace icecode {
  namespace test {

    class TimedTest : public Test
    {
    public:
      TimedTest() : Test() {}
      TimedTest(std::string desc) : Test(desc) {}

      virtual int start()
      {
	init();
	timerStart();

	try { run(); } catch (...) { test_fatal("Unexpected exception thrown. Please check your code."); ::exit(-1); }

	timerStop();
	printResult();
	printTime();
	return errors;
      }

      void printTime()
      {
	auto ival /*interval*/ = static_cast<long double>((ts_end.tv_nsec - ts_start.tv_nsec));
	std::cout << "Test time:\t\t" << std::setprecision(16) << ival << "ns (" << ival / 1000000 << "ms, " << ival / 1000000000 << "s)\n";
      }

    protected:
      ::timespec ts_start, ts_end;

      friend void icecode::test::internal_XMLOutput_TimedTest(icecode::test::TimedTest& t, xmlpp::Element* tst);

      void timerStart()
      {
	switch(::clock_gettime(CLOCK_MONOTONIC_RAW, &ts_start))
	  {
	  case EFAULT:
	  case EINVAL:
	  case EPERM:
	    std::cerr << "Error in timer startup.";
	    ::exit(-1);
	    break;
	  }
      }

      void timerStop()
      {
	switch(::clock_gettime(CLOCK_MONOTONIC_RAW, &ts_end))
	  {
	  case EFAULT:
	  case EINVAL:
	  case EPERM:
	    std::cerr << "Error in timer shutdown.";
	    ::exit(-1);
	    break;
	  }

      }
    };
  }
}

#endif //_ICECODE_GALILEI_TIMEDTEST
